package com.hua.Thread.reetrant;

/**
 * @author: _hua
 * @created: 2019/3/10.
 * @updater:
 * @description:
 */

/**
 * 当某个线程请求一个由其他线程持有的锁时，发出请求的线程就会阻塞。然而，由于内置锁是可重入的，
 * 因此如果摸个线程试图获得一个已经由它自己持有的锁，那么这个请求就会成功。
 * “重入”意味着获取锁的操作的粒度是“线程”，而不是调用。
 * 重入的一种实现方法是，为每个锁关联一个获取计数值和一个所有者线程。
 * 当计数值为0时，这个锁就被认为是没有被任何线程所持有，当线程请求一个未被持有的锁时，
 * JVM将记下锁的持有者，并且将获取计数值置为1，如果同一个线程再次获取这个锁，计数值将递增，
 * 而当线程退出同步代码块时，计数器会相应地递减。当计数值为0时，这个锁将被释放。
 *
 * 两个线程获取同一对象锁
 */
public class Father
{
    public synchronized void doSomething(){
       System.out.println("doSomething==========>"+Thread.currentThread());
        try {
            Thread.sleep(10000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public synchronized void doOtherSomething(){
        System.out.println("doOtherSomething==========>"+Thread.currentThread());
        try {
            Thread.sleep(10000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public static void main(String args[]){
        Father f = new Father();
        T1 t1 = new T1(f);
        T2 t2 = new T2(f);
        Thread th1 = new Thread(t1);
        th1.start();
        Thread th2 = new Thread(t2);
        th2.start();

    }
}
class T1 implements Runnable{
    Father f;
    T1(Father f){
        this.f=f;
    }

    @Override
    public void run() {
        f.doSomething();
        f.doOtherSomething();
        f.doSomething();
    }
}

class T2 implements Runnable{
    Father f;
    T2(Father f){
        this.f=f;
    }

    @Override
    public void run() {
        f.doOtherSomething();
    }
}